﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Remark: 适配jsoncpp/rapidjson，通过USE_RAPIDJSON来控制。写相关函数目前设为私有，如果有需要，可以改为public。
// 
#pragma once
#pragma warning(push)
#pragma warning(disable : 4003)
#include "GcmpDevService.h"
#include <memory>
#include <string>
#include "rapidjson/document.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/rapidjson.h"
#include "json/value.h"

//shenz 切换使用rapidjson/jsoncpp的开关，如果定义了USE_RAPIDJSON，则本单元使用rapidjson，否则使用jsoncpp
#define USE_RAPIDJSON

namespace gcmp
{
#ifdef USE_RAPIDJSON
    class GCMP_DEV_SERVICE_EXPORT GcmpJsonWrapper
    {
    public:
        bool Get(const std::string& strKey, std::string& strValue) const;
        bool Get(const std::string& strKey, int& iValue) const;
        bool Get(const std::string& strKey, int64_t& llValue) const;
        bool Get(const std::string& strKey, GcmpJsonWrapper& oJsonObject) const;
        bool Get(const std::string& strKey, double& dValue) const;
        bool GetBool(const std::string& strKey, bool& bValue) const;
        bool Get(int iWhich, GcmpJsonWrapper& oJsonObject) const;
        bool Get(int iWhich, int& iValue) const;
        bool Get(int iWhich, int64_t& llValue) const;
        bool Get(int iWhich, double& dValue) const;
        bool Get(int iWhich, std::string& strValue) const;

        bool Add(const std::string& strKey, double dValue);
        bool AddBool(const std::string& strKey, bool bValue);
        bool AddEmptySubObject(const std::string& strKey);
        bool AddEmptySubArray(const std::string& strKey);
        bool Add(int iValue);
        bool Add(int64_t llValue);
        bool Add(double dValue);
        

        bool Replace(const std::string& strKey, int iValue);
        bool Replace(const std::string& strKey, int64_t llValue);
        bool Replace(const std::string& strKey, const std::string& strValue);
        bool Replace(const std::string& strKey, const GcmpJsonWrapper& oJsonObject);

        rapidjson::Document::AllocatorType* GetAllocator() const { return m_pAllocator; }

    public:
        bool Add(const std::string& strKey, int iValue);
        bool Add(const std::string& strKey, int64_t llValue);
        bool Add(const std::string& strKey, const std::string& strValue); 
        bool Add(const std::string& strKey, const GcmpJsonWrapper& oJsonObject);
        bool Add(const std::string& strValue);
        std::string ToString() const;
        bool Clear();
        bool IsArray() const;
        bool IsObject() const;
        unsigned int GetArraySize() const;
        bool IsNull() const;
        GcmpJsonWrapper operator[](unsigned int index) const;
        GcmpJsonWrapper operator[](const std::string& strKey) const;

        int asInt() const;
        int64_t asInt64() const;
        std::string asString() const;
        bool asBool() const;
        double asDouble() const;
        unsigned asUInt() const;
        uint64_t asUInt64() const;

        bool HasMember(const std::string& strKey) const
        {
            return m_pValue->IsObject() && m_pValue->HasMember(strKey.c_str());
        }
        bool Add(const GcmpJsonWrapper& oJsonObject);
//        bool HasError() { return m_bParseError; }

        explicit GcmpJsonWrapper(const GcmpJsonWrapper* pJsonObject);
        GcmpJsonWrapper(const GcmpJsonWrapper& oJsonObject);
        virtual ~GcmpJsonWrapper();
        explicit GcmpJsonWrapper(rapidjson::Document::AllocatorType* pAllocator, rapidjson::Type type = rapidjson::kNullType);
        explicit GcmpJsonWrapper(rapidjson::Document* pDoc, bool bRef = true);
        GcmpJsonWrapper();
    private:
        void SetValue(rapidjson::Value* pValue);
        void SetValue(const GcmpJsonWrapper& oJsonObject);
    private:
        rapidjson::Value* m_pValue = nullptr;
        rapidjson::Document::AllocatorType* m_pAllocator = nullptr;
        rapidjson::Value::MemberIterator m_iterMember;
        bool m_bParseError = false;  //TODO: shenz 增加字符串参数的构造函数时需要，暂时保留
        bool m_bRef = true;  //控制是否负责json指针的生命周期，true表示只引用，不管理；false表示需要负责释放
    };

#else
    class GCMP_DEV_SERVICE_EXPORT GcmpJsonWrapper
    {
    private:
        bool Get(const std::string& strKey, std::string& strValue) const;
        bool Get(const std::string& strKey, int& iValue) const;
        bool Get(const std::string& strKey, int64_t& llValue) const;
        bool Get(const std::string& strKey, GcmpJsonWrapper& oJsonObject) const;
        bool Get(const std::string& strKey, double& dValue) const;
        bool GetBool(const std::string& strKey, bool& bValue) const;
        bool Get(int iWhich, GcmpJsonWrapper& oJsonObject) const;
        bool Get(int iWhich, int& iValue) const;
        bool Get(int iWhich, int64_t& llValue) const;
        bool Get(int iWhich, double& dValue) const;
        bool Get(int iWhich, std::string& strValue) const;

        bool Add(const std::string& strKey, int iValue);
        bool Add(const std::string& strKey, int64_t llValue);
        bool Add(const std::string& strKey, const std::string& strValue);
        bool Add(const std::string& strKey, double dValue);
        bool Add(const std::string& strKey, const GcmpJsonWrapper& oJsonObject);
        bool AddBool(const std::string& strKey, bool bValue);
        bool Add(const GcmpJsonWrapper& oJsonObject);
        bool AddEmptySubObject(const std::string& strKey);
        bool AddEmptySubArray(const std::string& strKey);
        bool Add(int iValue);
        bool Add(int64_t llValue);
        bool Add(double dValue);
        bool Add(const std::string& strValue);

        bool Replace(const std::string& strKey, int iValue);
        bool Replace(const std::string& strKey, int64_t llValue);
        bool Replace(const std::string& strKey, const std::string& strValue);
        bool Replace(const std::string& strKey, const GcmpJsonWrapper& oJsonObject);

        std::string ToString() const;
    public:
        bool IsArray() const;
        bool IsObject() const;
        unsigned int GetArraySize() const;
        bool IsNull() const;
        GcmpJsonWrapper operator[](unsigned int index) const;
        GcmpJsonWrapper operator[](const std::string& strKey) const;
        bool Clear();
        int asInt() const;
        int64_t asInt64() const;
        std::string asString() const;
        bool asBool() const;
        double asDouble() const;
        unsigned asUInt() const;
        uint64_t asUInt64() const;

        bool HasMember(const std::string& strKey) const
        {
            return m_pValue->isObject() && m_pValue->isMember(strKey.c_str());
        }

//        bool HasError() { return m_bParseError; }

        explicit GcmpJsonWrapper(const GcmpJsonWrapper* pJsonObject);
        GcmpJsonWrapper(const GcmpJsonWrapper& oJsonObject);
        virtual ~GcmpJsonWrapper();
        explicit GcmpJsonWrapper(const Json::Value *pValue, bool bRef = true);
        GcmpJsonWrapper();
    private:
        void SetValue(Json::Value* pValue);
        void SetValue(const GcmpJsonWrapper& oJsonObject);
    private:
        Json::Value* m_pValue = nullptr;
        bool m_bParseError = false; //TODO: shenz 增加字符串参数的构造函数时需要，暂时保留
        bool m_bRef = true; //控制是否负责json指针的生命周期，true表示只引用，不管理；false表示需要负责释放
    };
#endif
}

#pragma warning(pop)
